#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "t3.h"



int main(int argc, char *argv[]) {
	FILE *arq;

	int i, j, t;
	float d;
	int end_loop;
	int erro;

	int J_ORDER, J_ROW_TEST, J_ITE_MAX;
	float J_ERROR;
	float **MA;
	float *MB;
	float *X;
	float *X_;
	float *Dif;
	int k;
	float sum, mr;
	
	
	/*** tratamento de erro de parametros ***/
	if ((argc < 2) || (argc > 2)) {
		fprintf(stderr, ">> main::argc\n");
		return (-1);
	}


	/*** Abre arquivo ***/
	if ((arq = fopen(argv[1], "r+")) == NULL) {
		fprintf(stderr, ">> main::fopen(%s)\n", argv[1]);
		return (-1);
	}


	/*** Leitura do arquivo (informacoes basicas) ***/
	fscanf(arq, "%d\n", &J_ORDER);
	printf("J_ORDER: %d\n", J_ORDER);
	fscanf(arq, "%d\n", &J_ROW_TEST);
	printf("J_ROW_TEST: %d\n", J_ROW_TEST);
	fscanf(arq, "%f\n", &J_ERROR);
	printf("J_ERROR: %lf\n", J_ERROR);
	fscanf(arq, "%d", &J_ITE_MAX);
	printf("J_ITE_MAX: %d\n", J_ITE_MAX);


	/*** Aloca matriz e vetor ***/
	MA = alocaMatriz(J_ORDER, J_ORDER);
	MB = alocaVetor(J_ORDER);
	X = alocaVetor(J_ORDER);
	X_ = alocaVetor(J_ORDER);
	Dif = alocaVetor(J_ORDER);


	/*** Leitura do arquivo (matriz MA) ***/
	for (i = 0; i < J_ORDER; i++) {
		for (j = 0; j < J_ORDER; j++) {
			fscanf(arq, "%d", &t);
			MA[i][j] = t;
		}
	}
	printf("leitura MA ok\n");


	/*** Leitura do arquivo (vetor MB) ***/
	for (i = 0; i < J_ORDER; i++) {
		fscanf(arq, "%d", &t);
		MB[i] = t;
	}
	printf("leituta MB ok\n");


	/*** Inicializa o X_ para k = 0 ***/
	for (i = 0; i < J_ORDER; i++) {
		X_[i] = MB[i] / MA[i][i];
	}
	printf("inicializacao de X_ ok\n");


	printf("calculando X...\n");
	/*** Calcula o X ateh chegar no valor da iteracao maxima ou chegar perto do erro aproximado ***/
	k = 0;
	end_loop = FALSE;
	while (!end_loop) {
		//if (k % 100 == 0) printf("#%d ", k);
		// acha o X(k+1)
		for (i = 0; i < J_ORDER; i++) {
			d = 0.0f;
			// soma os elementos que sao multiplicados por X[]
			for (j = 0; j < J_ORDER; j++) {
				if (i != j) {
					d = d + (MA[i][j] / MA[i][i]) * X_[j];
				}
				// se i == j nao faz nada, pois multiplica X[i] por 0
				// e na soma nao acontece nada
			}
			X[i] = -(d) + MB[i] / MA[i][i];
		}

		// muda a iteracao
		k++;

		// acha o mr(k+1)
		for (i = 0; i < J_ORDER; i++) {
			Dif[i] = fabs(X[i] - X_[i]);
		}
		mr = valorMaxVetor(Dif, J_ORDER, NORMAL) / valorMaxVetor(X, J_ORDER, ABSOLUTE);

		//imprimeVetor(Dif, J_ORDER);printf("mr: %f\n", mr);
		
		// teste de saida por iteracao limite ou pelo mr estar proximo
		// do erro de precisao
		if ((k >= J_ITE_MAX) || (mr <= J_ERROR)) {
			end_loop = TRUE;
		} else {
			// caso ainda continue, entao atualiza X anterior
			// x(k) = x(k+1)
			for (i = 0; i < J_ORDER; i++) {
				X_[i] = X[i];
			}
		}
	}
	printf("calculo de X ok\n");


	/*** Calcula o RowTest ***/
	sum = 0.0f;
	// calcula o valor da linha i, onde o valor eh A[i,j]*X[j]
	for (j = 0; j < J_ORDER; j++) {
		sum = sum + MA[J_ROW_TEST][j] * X[j];
	}

	printf("---------------------------------------------------------\n");
	printf("Iterations: %d\n", k);
	printf("RowTest: %d => [%f] =? %f\n", J_ROW_TEST, sum, MB[J_ROW_TEST]);
	printf("---------------------------------------------------------\n");


	/*** Desaloca da memoria ***/
	desalocaMatriz(MA, J_ORDER, J_ORDER);
	desalocaVetor(MB);
	desalocaVetor(X);
	desalocaVetor(X_);
	desalocaVetor(Dif);
	fclose(arq);

	return 0;
}
